package lab.bmp.track;

import lab.bmp.genre.*;
import java.rmi.RemoteException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import javax.ejb.CreateException;
import javax.ejb.EJBException;
import javax.ejb.EntityBean;
import javax.ejb.EntityContext;
import javax.ejb.FinderException;
import javax.ejb.RemoveException;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import lab.bmp.artist.ArtistPK;
import lab.bmp.studio.StudioPK;
import lab.domain.ChangableHashSet;
import lab.domain.SoundRecordingStudio;
import lab.logging.LoggingUtil;
import ru.ssau.DatabaseHelper;

/**
 *
 * @author Smike
 */
public class TrackBean implements EntityBean {

    EntityContext context;
    DataSource datasource;
    boolean initialized;
    Collection<GenrePK> genres;
    Collection<ArtistPK> artists;
    StudioPK studio;
    String name;
    Long length;
    Integer year;
    boolean changed;

    public void setEntityContext(EntityContext ctx) throws EJBException, RemoteException {
        this.context = ctx;
        try {
        } catch (Exception e) {
            throw new EJBException(e);
        }
    }

    public void unsetEntityContext() throws EJBException, RemoteException {
        this.context = null;
    }

    public void ejbRemove() throws RemoveException, EJBException, RemoteException {
        TrackPK key = getCurrentKey();
        lab.domain.Track track = new lab.domain.Track();
        track.setId(key.getId());
        Connection connection = getConnection();
        try {
            DatabaseHelper.deleteTrack(connection, track);
        } catch (SQLException ex) {
            throw new RemoveException(ex.getMessage());
        } finally {
            try {
                connection.close();
            } catch (Exception e) {
            }
        }
    }

    public void ejbActivate() throws EJBException, RemoteException {
        // do nothing
    }

    public void ejbPassivate() throws EJBException, RemoteException {
    }

    public void ejbLoad() throws EJBException, RemoteException {
        changed = false;
        // lazy
    }

    private void initializeIfNeeded() {
        if (!initialized) {
            TrackPK key = getCurrentKey();
            Connection connection = getConnection();
            try {
                lab.domain.Track track = DatabaseHelper.findTrack(connection, key.getId());
                name = track.getName();
                length = track.getLength();
                year = track.getYear();

                genres = new ArrayList<GenrePK>();
                for (lab.domain.Genre genre : track.getGenres()) {
                    genres.add(new GenrePK(genre.getId()));
                }

                artists = new ArrayList<ArtistPK>();
                for (lab.domain.Artist artist : track.getArtists()) {
                    artists.add(new ArtistPK(artist.getId()));
                }

                studio = new StudioPK(track.getSoundRecordingStudio().getId());
                initialized = true;
            } catch (SQLException ex) {
                throw new EJBException(ex.getMessage());
            } finally {
                try {
                    connection.close();
                } catch (Exception e) {
                }
            }
        }
    }

    public void ejbStore() throws EJBException, RemoteException {
        if (initialized && changed) {
            lab.domain.Track track = new lab.domain.Track();
            track.setId(getCurrentKey().getId());
            track.setName(name);
            track.setLength(length);
            track.setYear(year);

            ChangableHashSet<lab.domain.Genre> trackGenres = new ChangableHashSet<lab.domain.Genre>();
            for (GenrePK genre : genres) {
                lab.domain.Genre g = new lab.domain.Genre();
                g.setId(genre.getId());
                trackGenres.add(g);
            }
            track.setGenres(trackGenres);

            ChangableHashSet<lab.domain.Artist> trackArtists = new ChangableHashSet<lab.domain.Artist>();
            for (ArtistPK artist : artists) {
                lab.domain.Artist a = new lab.domain.Artist();
                a.setId(artist.getId());
                trackArtists.add(a);
            }
            track.setArtists(trackArtists);

            SoundRecordingStudio s = new SoundRecordingStudio();
            s.setId(studio.getId());
            track.setSoundRecordingStudio(s);

            Connection connection = getConnection();
            try {
                DatabaseHelper.updateTrack(connection, track);
                LoggingUtil.log(LoggingUtil.TRACK);
            } catch (SQLException ex) {
                throw new EJBException(ex.getMessage());
            } finally {
                try {
                    connection.close();
                } catch (Exception e) {
                }
            }
        }
    }

    TrackPK getCurrentKey() {
        return (TrackPK) context.getPrimaryKey();
    }

    public Integer getId() {
        return getCurrentKey().getId();
    }

    public void setId(Integer id) {
        throw new UnsupportedOperationException();
    }

    public Collection<GenrePK> getGenres() {
        initializeIfNeeded();
        return genres;
    }

    public void setGenres(Collection<GenrePK> genres) {
        initializeIfNeeded();
        this.genres = genres;
        changed = true;
    }

    public void setArtists(Collection<ArtistPK> artists) {
        initializeIfNeeded();
        this.artists = artists;
        changed = true;
    }

    public Collection<ArtistPK> getArtists() {
        initializeIfNeeded();
        return artists;
    }

    public StudioPK getStudio() {
        initializeIfNeeded();
        return studio;
    }

    public void setStudio(StudioPK studio) {
        initializeIfNeeded();
        this.studio = studio;
        changed = true;
    }

    public Long getLength() {
        initializeIfNeeded();
        return length;
    }

    public void setLength(Long length) {
        initializeIfNeeded();
        this.length = length;
        changed = true;
    }

    public String getName() {
        initializeIfNeeded();
        return name;
    }

    public void setName(String name) {
        initializeIfNeeded();
        this.name = name;
        changed = true;
    }

    public Integer getYear() {
        initializeIfNeeded();
        return year;
    }

    public void setYear(Integer year) {
        initializeIfNeeded();
        this.year = year;
        changed = true;
    }

    public TrackPK ejbCreate(Integer id, Collection<GenrePK> genres, Collection<ArtistPK> artists, StudioPK studio, String name, Long length, Integer year) throws CreateException {
        lab.domain.Track track = new lab.domain.Track();
        track.setId(getCurrentKey().getId());
        track.setName(name);
        track.setLength(length);
        track.setYear(year);

        ChangableHashSet<lab.domain.Genre> trackGenres = new ChangableHashSet<lab.domain.Genre>();
        for (GenrePK genre : genres) {
            lab.domain.Genre g = new lab.domain.Genre();
            g.setId(genre.getId());
            trackGenres.add(g);
        }
        track.setGenres(trackGenres);

        ChangableHashSet<lab.domain.Artist> trackArtists = new ChangableHashSet<lab.domain.Artist>();
        for (ArtistPK artist : artists) {
            lab.domain.Artist a = new lab.domain.Artist();
            a.setId(artist.getId());
            trackArtists.add(a);
        }
        track.setArtists(trackArtists);

        SoundRecordingStudio s = new SoundRecordingStudio();
        s.setId(studio.getId());
        track.setSoundRecordingStudio(s);

        Connection connection = getConnection();
        try {
            return new TrackPK(DatabaseHelper.insertTrack(connection, track));
        } catch (SQLException ex) {
            throw new EJBException(ex.getMessage());
        } finally {
            try {
                connection.close();
            } catch (Exception e) {
            }
        }
    }

    public TrackPK ejbFindByPrimaryKey(TrackPK key) throws FinderException {
        Connection connection = getConnection();
        try {
            DatabaseHelper.findTrack(connection, key.getId());
            return key;
        } catch (SQLException ex) {
            throw new FinderException(ex.getMessage());
        } finally {
            try {
                connection.close();
            } catch (Exception e) {
            }
        }
    }

    public Collection ejbFindAll() throws FinderException {
        Connection connection = getConnection();
        try {
            Collection<lab.domain.Track> tracks = DatabaseHelper.findTracks(connection);
            Collection<TrackPK> keys = new ArrayList<TrackPK>();
            for (lab.domain.Track track : tracks) {
                keys.add(new TrackPK(track.getId()));
            }
            return keys;
        } catch (SQLException ex) {
            throw new FinderException(ex.getMessage());
        } finally {
            try {
                connection.close();
            } catch (Exception e) {
            }
        }
    }

    Connection getConnection() {
        try {
            return getDataSource().getConnection();
        } catch (SQLException ex) {
            throw new RuntimeException(ex);
        }
    }

    DataSource getDataSource() {
        if (datasource == null) {
            try {
                datasource = (DataSource) new InitialContext().lookup("oracleDS");
                return datasource;
            } catch (NamingException ex) {
                throw new RuntimeException(ex);
            }
        }
        return datasource;
    }
}
